//
//  YZVideoVC.m
//  VET
//
//  Created by YZ on 2018/7/11.
//  Copyright © 2018年 YZ. All rights reserved.
//

#import "YZVideoVC.h"
#import <AVFoundation/AVFoundation.h>
#import "YZVideoPlayer.h"
#import "YZVideoProgressView.h"
#import "YZCoreMotionManager.h"

@interface YZVideoVC ()<UIAlertViewDelegate,UIGestureRecognizerDelegate,AVCaptureFileOutputRecordingDelegate,YZVideoProgressViewDelegate>

@property (nonatomic, assign) AVCaptureVideoOrientation currentOrientation;

//捕获设备，通常是前置摄像头，后置摄像头，麦克风（音频输入）
@property (nonatomic, strong) AVCaptureDevice *device;

//视频输出流
@property (nonatomic, strong) AVCaptureMovieFileOutput *captureMovieFileOutput;

//负责从AVCaptureDevice获得输入数据
@property (nonatomic, strong) AVCaptureDeviceInput *captureDeviceInput;

//负责输入和输出设备之间的数据传递
@property (nonatomic, strong) AVCaptureSession *session;

//图像预览层，实时显示捕获的图像
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer;

@property (nonatomic, strong) AVCaptureConnection *connection;

@property (nonatomic, strong) YZCoreMotionManager* manager;

// ------------- UI --------------

@property (nonatomic, strong) YZVideoPlayer *player;

@property (nonatomic, strong) UIButton *closeBtn;

@property (nonatomic, strong) UIButton *flashBtn;

@property (nonatomic, strong) UIButton *switchBtn;

@property (nonatomic, strong) YZVideoProgressView *progressView;

@property (nonatomic, strong) UIButton *cancelBtn;

@property (nonatomic, strong) UIButton *confirmBtn;
//聚焦
@property (nonatomic, strong) UIView *focusView;

@property (nonatomic, assign) CGFloat beginGestureScale;

@property (nonatomic, assign) CGFloat effectiveScale;

@property (nonatomic, strong) PHAsset *currentAssert;

@property (nonatomic, strong) NSURL *currentAssertUrl;

@end

@implementation YZVideoVC

- (instancetype)init
{
    if (self = [super init]) {
        //监听当前屏幕方向
        self.manager = [[YZCoreMotionManager alloc] init];
        [self.manager startUpdateCurrentOrientation];
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.beginGestureScale = 1.0;
    self.view.backgroundColor = [UIColor blackColor];
    if ( [self checkCameraPermission]) {
        //创建视频预览层，用于实时展示摄像头状态
        self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] init];
        self.previewLayer.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight);
        self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
        [self.view.layer addSublayer:self.previewLayer];
        [self initUI];
        [self customCamera];
        [self focusAtPoint:CGPointMake(0.5, 0.5)];
        UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(focusGesture:)];
        [self.view addGestureRecognizer:tapGesture];
        
        UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(adjustFocasDistance:)];
        pinchGesture.delegate = self;
        [self.view addGestureRecognizer:pinchGesture];
    }
}

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];
}

- (void)dealloc
{
    [self.player stopPlayer];
}

- (AVCaptureDevice *)getCameraDeviceWithPosition:(AVCaptureDevicePosition )position
{
    NSArray *cameras= [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    for (AVCaptureDevice *camera in cameras) {
        if ([camera position] == position) {
            return camera;
        }
    }
    return nil;
}

- (void)customCamera
{
    //初始化会话，用来结合输入输出
    self.session = [[AVCaptureSession alloc] init];
    //设置分辨率 (设备支持的最高分辨率)
    if ([self.session canSetSessionPreset:AVCaptureSessionPresetHigh]) {
        self.session.sessionPreset = AVCaptureSessionPresetHigh;
    }
    //取得后置摄像头
    self.device = [self getCameraDeviceWithPosition:AVCaptureDevicePositionBack];
    //添加一个音频输入设备
    AVCaptureDevice *audioCaptureDevice=[[AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio] firstObject];
    
    //初始化输入设备
    NSError *error = nil;
    self.captureDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:self.device error:&error];
    if (error) {
        NSLog(@"取得设备输入对象时出错，错误原因：%@",error.localizedDescription);
        return;
    }
    
    //添加音频
    error = nil;
    AVCaptureDeviceInput *audioCaptureDeviceInput=[[AVCaptureDeviceInput alloc]initWithDevice:audioCaptureDevice error:&error];
    if (error) {
        NSLog(@"取得设备输入对象时出错，错误原因：%@",error.localizedDescription);
        return;
    }
    
    //输出对象
    self.captureMovieFileOutput = [[AVCaptureMovieFileOutput alloc] init];//视频输出
    
    //将输入设备添加到会话
    if ([self.session canAddInput:self.captureDeviceInput]) {
        [self.session addInput:self.captureDeviceInput];
        [self.session addInput:audioCaptureDeviceInput];
        //设置视频防抖
        self.connection = [self.captureMovieFileOutput connectionWithMediaType:AVMediaTypeVideo];
        if ([self.connection isVideoStabilizationSupported]) {
            self.connection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeCinematic;
        }
    }
    
    //将输出设备添加到会话 (刚开始 是照片为输出对象)
    if ([self.session canAddOutput:self.captureMovieFileOutput]) {
        [self.session addOutput:self.captureMovieFileOutput];
    }
    
    //修改设备的属性，先加锁
    if ([self.device lockForConfiguration:nil]) {
        //闪光灯关闭
        if ([self.device isFlashModeSupported:AVCaptureFlashModeOff]) {
            [self.device setFlashMode:AVCaptureFlashModeOff];
        }
        
        //自动白平衡
        if ([self.device isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeAutoWhiteBalance]) {
            [self.device setWhiteBalanceMode:AVCaptureWhiteBalanceModeAutoWhiteBalance];
        }
        //解锁
        [self.device unlockForConfiguration];
    }
    
    self.previewLayer.session = self.session;
    [self.session startRunning];
}

- (void)initUI
{
    [self.view addSubview:self.focusView];
    [self.view addSubview:self.player];
    [self.view addSubview:self.closeBtn];
    [self.view addSubview:self.switchBtn];
    [self.view addSubview: self.flashBtn];
    [self.view addSubview:self.progressView];
    [self.view addSubview:self.cancelBtn];
    [self.view addSubview:self.confirmBtn];
    
    [self makeContraints];
}

    
- (void)makeContraints
{
    [self.player mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(self.view).insets(UIEdgeInsetsZero);
    }];
    
    [self.closeBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.mas_equalTo(kCurrentDeviceNum(40));
        make.size.mas_equalTo(CGSizeMake(kCurrentDeviceNum(16), kCurrentDeviceNum(16)));
        make.left.mas_equalTo(kCurrentDeviceNum(15));
    }];

    [self.switchBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.right.equalTo(self.view.mas_right).offset(-kCurrentDeviceNum(30));
        make.size.mas_equalTo(CGSizeMake(kCurrentDeviceNum(28), kCurrentDeviceNum(28)));
        make.centerY.equalTo(self.closeBtn);
    }];
    
    [self.flashBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.right.equalTo(self.switchBtn.mas_left).offset(-kCurrentDeviceNum(20));
        make.size.equalTo(self.switchBtn);
        make.centerY.equalTo(self.closeBtn);
    }];
    
    [self.progressView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.equalTo(self.view);
        make.size.mas_equalTo(CGSizeMake(kMaxProgressViewWidth, kMaxProgressViewHeight));
        make.bottom.equalTo(self.view.mas_bottom).offset(-kCurrentDeviceNum(50));
    }];
    
    [self.cancelBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerY.equalTo(self.progressView);
        make.size.mas_equalTo(CGSizeMake(kCurrentDeviceNum(80), kCurrentDeviceNum(80)));
        make.right.equalTo(self.progressView.mas_left).offset(-kCurrentDeviceNum(10));
    }];
    
    [self.confirmBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerY.equalTo(self.progressView);
        make.size.mas_equalTo(CGSizeMake(kCurrentDeviceNum(80), kCurrentDeviceNum(80)));
        make.left.equalTo(self.progressView.mas_right).offset(kCurrentDeviceNum(10));
    }];
}

- (void)focusGesture:(UITapGestureRecognizer *)gesture
{
    CGPoint point = [gesture locationInView:gesture.view];
    [self focusAtPoint:point];
}

- (void)focusAtPoint:(CGPoint)point
{
    CGSize size = self.view.bounds.size;
    // focusPoint 函数后面Point取值范围是取景框左上角（0，0）到取景框右下角（1，1）之间,按这个来但位置就是不对，只能按上面的写法才可以。前面是点击位置的y/PreviewLayer的高度，后面是1-点击位置的x/PreviewLayer的宽度
    CGPoint focusPoint = CGPointMake( point.y /size.height ,1 - point.x/size.width );
    
    if ([self.device lockForConfiguration:nil]) {
        
        if ([self.device isFocusModeSupported:AVCaptureFocusModeAutoFocus]) {
            [self.device setFocusPointOfInterest:focusPoint];
            [self.device setFocusMode:AVCaptureFocusModeAutoFocus];
        }
        
        if ([self.device isExposureModeSupported:AVCaptureExposureModeAutoExpose ]) {
            [self.device setExposurePointOfInterest:focusPoint];
            //曝光量调节
            [self.device setExposureMode:AVCaptureExposureModeAutoExpose];
        }
        
        [self.device unlockForConfiguration];
        self.focusView.center = point;
        self.focusView.hidden = NO;
        [UIView animateWithDuration:0.3 animations:^{
            self.focusView.transform = CGAffineTransformMakeScale(1.25, 1.25);
        }completion:^(BOOL finished) {
            [UIView animateWithDuration:0.5 animations:^{
                self.focusView.transform = CGAffineTransformIdentity;
            } completion:^(BOOL finished) {
                self.focusView.hidden = YES;
            }];
        }];
    }
}

- (void)flashBtnClicked
{
    self.flashBtn.selected = !self.flashBtn.selected;
    if ([_device lockForConfiguration:nil]) {
        BOOL selected = self.flashBtn.selected;
        if ([_device isFlashModeSupported:!selected?AVCaptureFlashModeOff:AVCaptureFlashModeOn]) {
            [_device setFlashMode:!selected?AVCaptureFlashModeOff:AVCaptureFlashModeOn];
        }
        [_device unlockForConfiguration];
    }
}

- (void)switchBtnClicked
{
    //获取摄像头的数量
    NSUInteger cameraCount = [[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] count];
    //摄像头小于等于1的时候直接返回
    if (cameraCount <= 1) return;
    AVCaptureDevice *newCamera = nil;
    AVCaptureDeviceInput *newInput = nil;
    //获取当前相机的方向(前还是后)
    AVCaptureDevicePosition position = [[self.captureDeviceInput device] position];
    
    //为摄像头的转换加转场动画
    CATransition *animation = [CATransition animation];
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    animation.duration = 0.5;
    animation.type = @"oglFlip";
    
    if (position == AVCaptureDevicePositionFront) {
        //获取后置摄像头
        newCamera = [self cameraWithPosition:AVCaptureDevicePositionBack];
        animation.subtype = kCATransitionFromLeft;
    }else{
        //获取前置摄像头
        newCamera = [self cameraWithPosition:AVCaptureDevicePositionFront];
        animation.subtype = kCATransitionFromRight;
    }
    
    [self.previewLayer addAnimation:animation forKey:nil];
    //输入流
    newInput = [AVCaptureDeviceInput deviceInputWithDevice:newCamera error:nil];
    if (newInput != nil) {
        [self.session beginConfiguration];
        //先移除原来的input
        [self.session removeInput:self.captureDeviceInput];
        if ([self.session canAddInput:newInput]) {
            [self.session addInput:newInput];
            self.captureDeviceInput = newInput;
        } else {
            //如果不能加现在的input，就加原来的input
            [self.session addInput:self.captureDeviceInput];
        }
        [self.session commitConfiguration];
    }
}

- (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition)position
{
    NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    for ( AVCaptureDevice *device in devices )
        if (device.position == position )
            return device;
    return nil;
}

-(void)adjustFocasDistance:(UIPinchGestureRecognizer *)ges
{
    if (ges.state != UIGestureRecognizerStateChanged) return;
    self.effectiveScale = self.beginGestureScale*ges.scale;
    if (self.effectiveScale <= 1)
        self.effectiveScale = 1.0;

    if(self.effectiveScale > 10.0)
        self.effectiveScale = 1.0;
    [self.device lockForConfiguration:nil];
    [self.device rampToVideoZoomFactor:self.effectiveScale withRate:10];
    [self.device unlockForConfiguration];
}

#pragma mark- 录制

- (void)cancelBtnClicked
{
    self.player.hidden = self.cancelBtn.hidden = self.confirmBtn.hidden = YES;
    self.flashBtn.hidden = self.switchBtn.hidden = NO;
    self.progressView.hidden = NO;
    self.previewLayer.hidden = NO;
    [self.player stopPlayer];
    
    self.currentAssert = nil;
}

- (void)confirmBtnClicked
{
    [YZMediaSourceManager saveFile:self.currentAssertUrl completionHandler:^(BOOL success, NSError * _Nullable error,PHAsset *assert) {
        if (!error && success) {
            NSLog(@"保存相册成功!");
            if (assert) {
                self.currentAssert = assert;
                if (self.delegate && [self.delegate respondsToSelector:@selector(getCurrentVideoAssert:andUrl:andCurrentOrientation:)]) {
                    [self.delegate getCurrentVideoAssert:self.currentAssert andUrl:self.currentAssertUrl andCurrentOrientation:self.currentOrientation];
                }
            }
        }
        else {
            NSLog(@"保存相册失败! :%@",error);
        }
    }];
    [self dismissViewControllerAnimated:YES completion:NO];
}

- (void)closeBtnClicked
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

#pragma mark- 检测相机权限

- (BOOL)checkCameraPermission
{
    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    if (authStatus == AVAuthorizationStatusDenied) {
        UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"请打开相机权限" message:@"设置-隐私-相机" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:@"取消", nil];
        alertView.tag = 100;
        [alertView show];
        return NO;
    }
    else{
        return YES;
    }
    return YES;
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    if (buttonIndex == 0 && alertView.tag == 100) {
        
        NSURL * url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
        
        if([[UIApplication sharedApplication] canOpenURL:url]) {
            
            [[UIApplication sharedApplication] openURL:url];
        }
    }
    
    if (buttonIndex == 1 && alertView.tag == 100) {
        [self closeBtnClicked];
    }
}

#pragma mark -- YZVideoProgressViewDelegate

- (void)progressStarted
{
    self.cancelBtn.hidden = self.confirmBtn.hidden = YES;
    self.connection = [self.captureMovieFileOutput connectionWithMediaType:AVMediaTypeVideo];
    self.currentOrientation = [self.manager getCurrentOrientation];
    if([self.connection isVideoOrientationSupported]) {
        switch (self.currentOrientation) {
            case AVCaptureVideoOrientationLandscapeLeft:
            {
                [self.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeLeft];
            }
                break;
            case AVCaptureVideoOrientationLandscapeRight:
            {
                [self.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
            }
                break;
            case AVCaptureVideoOrientationPortraitUpsideDown:
            {
                [self.connection setVideoOrientation:AVCaptureVideoOrientationPortraitUpsideDown];
            }
                break;
            case AVCaptureVideoOrientationPortrait:
            {
                [self.connection setVideoOrientation: AVCaptureVideoOrientationPortrait];
            }
                break;
        }
    }
    [self.manager stoptUpdateCurrentOrientation];
    //根据连接取得设备输出的数据
    if (![self.captureMovieFileOutput isRecording]) {
        //预览图层和视频方向保持一致
//        connection.videoOrientation = [self.previewLayer connection].videoOrientation;
        NSString *outputFielPath=[NSTemporaryDirectory() stringByAppendingString:@"myMovie.mov"];
        NSLog(@"save path is :%@",outputFielPath);
        NSURL *fileUrl=[NSURL fileURLWithPath:outputFielPath];
        NSLog(@"fileUrl:%@",fileUrl);
        [self.captureMovieFileOutput startRecordingToOutputFileURL:fileUrl recordingDelegate:self];
    } else {
        [self.captureMovieFileOutput stopRecording];
    }
}

- (void)progressEnded
{
    if ([self.captureMovieFileOutput isRecording]) {
        [self.captureMovieFileOutput stopRecording];
    }
}

#pragma mark -- AVCaptureFileOutputRecordingDelegate

-(void)captureOutput:(AVCaptureFileOutput *)captureOutput didStartRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray *)connections
{
    NSLog(@"开始录制...");
}

-(void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error
{
    NSLog(@"视频录制完成.");
    self.flashBtn.hidden = self.switchBtn.hidden = YES;
    self.cancelBtn.hidden = self.confirmBtn.hidden = NO;
    self.player.hidden = NO;
    self.previewLayer.hidden = YES;
    self.progressView.hidden = YES;
    self.player.videoUrl = outputFileURL;
    [self.player startPlayer];
    
    self.currentAssertUrl = outputFileURL;
}

#pragma mark -- UIGestureRecognizerDelegate

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    if ([gestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]] ) {
        self.beginGestureScale = self.effectiveScale;
    }
    return YES;
}

#pragma  mark -- setters && getters

- (YZVideoPlayer *)player
{
    if (!_player) {
        _player = [YZVideoPlayer new];
        _player.hidden = YES;
    }
    return _player;
}

- (UIButton *)closeBtn
{
    if (!_closeBtn) {
        _closeBtn = [UIButton new];
        [_closeBtn setImage:[UIImage imageNamed:@"ico_back_white"] forState:UIControlStateNormal];
        [_closeBtn addTarget:self action:@selector(closeBtnClicked) forControlEvents:UIControlEventTouchUpInside];
    }
    return _closeBtn;
}

- (UIButton *)flashBtn
{
    if (!_flashBtn) {
        _flashBtn = [UIButton new];
        [_flashBtn setImage:[UIImage imageNamed:@"ico_camera_flash_off"] forState:UIControlStateNormal];
        [_flashBtn setImage:[UIImage imageNamed:@"ico_camera_flash"] forState:UIControlStateSelected];
        [_flashBtn addTarget:self action:@selector(flashBtnClicked) forControlEvents:UIControlEventTouchUpInside];
    }
    return _flashBtn;
}

- (UIButton *)switchBtn
{
    if (!_switchBtn) {
        _switchBtn = [UIButton new];
        [_switchBtn setImage:[UIImage imageNamed:@"ico_camera_fz"] forState:UIControlStateNormal];
        [_switchBtn addTarget:self action:@selector(switchBtnClicked) forControlEvents:UIControlEventTouchUpInside];
    }
    return _switchBtn;
}

- (YZVideoProgressView *)progressView
{
    if (!_progressView) {
        _progressView = [YZVideoProgressView new];
        _progressView.timeMax = 10;
        _progressView.delegate = self;
    }
    return _progressView;
}

- (UIButton *)cancelBtn
{
    if (!_cancelBtn) {
        _cancelBtn = [UIButton new];
        _cancelBtn.hidden = YES;
        _cancelBtn.backgroundColor = [UIColor clearColor];
        [_cancelBtn setImage:[UIImage imageNamed:@"ass_btn_camera_black"] forState:UIControlStateNormal];
        [_cancelBtn addTarget:self action:@selector(cancelBtnClicked) forControlEvents:UIControlEventTouchUpInside];
    }
    return _cancelBtn;
}

- (UIButton *)confirmBtn
{
    if (!_confirmBtn) {
        _confirmBtn = [UIButton new];
        _confirmBtn.hidden = YES;
        _confirmBtn.backgroundColor = [UIColor clearColor];
        [_confirmBtn setImage:[UIImage imageNamed:@"ass_btn_camera_sumbit"] forState:UIControlStateNormal];
        [_confirmBtn addTarget:self action:@selector(confirmBtnClicked) forControlEvents:UIControlEventTouchUpInside];
    }
    return _confirmBtn;
}

- (UIView *)focusView
{
    if (!_focusView) {
        _focusView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 80, 80)];
        _focusView.layer.borderWidth = 1.0;
        _focusView.layer.borderColor = [UIColor greenColor].CGColor;
        _focusView.hidden = YES;
    }
    return _focusView;
}

- (UIDeviceOrientation)getCcurrentOrientation
{
    return self.currentOrientation;
}

@end
